package com.nth.rooster.authentication.services;

import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.nth.rooster.authentication.beans.LoginBean;
import com.nth.rooster.authentication.beans.OrganisationInfoBean;
import com.nth.rooster.authentication.dao.AuthenticationDaoI;
import com.nth.rooster.authentication.exception.LoginException;
import com.nth.rooster.core.constants.RoosterConstants;
import com.nth.rooster.core.dao.DBUtilsDAO;
import com.nth.rooster.core.entities.RamLogins;
import com.nth.rooster.core.entities.RamRoles;
import com.nth.rooster.core.entities.RamSystemSettings;
import com.nth.rooster.core.exception.NErrorCode;
import com.nth.rooster.core.exception.RoosterCoreException;
import com.nth.rooster.core.exception.UnknownSystemKeyException;
import com.nth.rooster.core.pojo.AuthenticationBean;
import com.nth.rooster.core.utils.DBUtils;

@Service
public class AuthenticationService implements AuthenticationServiceI {

	static Logger LOGGER = Logger.getLogger(AuthenticationService.class);

	@Autowired
	private AuthenticationDaoI authenticationDaoI;

	@Autowired
	private DBUtilsDAO dbUtilsDAO;

	public AuthenticationBean login(LoginBean loginBean) {
		RamLogins ramLogins = authenticationDaoI.login(loginBean);
		
		/*
		 *  @TODO
		 *  1)check if the user is active or not. 
		 *  If the user is active.
		 *  2) Update the failure count i.e 
		 *  number of time authentication  failed.
		 *  
		 *  
		 */
		 
		if (ramLogins == null) {
			throw new LoginException(NErrorCode.INVALID_LOGIN_AUTHENTICATION,
					loginBean.getUsername());
		}
		/*
		 * Update the last_sucessful_login. 
		 */
		return mapAuthenticationBean(ramLogins);
	}

	public OrganisationInfoBean validateURL() {
		OrganisationInfoBean organisationInfoBean = new OrganisationInfoBean();
		organisationInfoBean.setOrganisationName("sdafsd");

		return organisationInfoBean;
	}

	public AuthenticationBean validateSuperUserInitialSignIn(LoginBean loginBean) {

		LOGGER.info("Entered::Authentication::AuthenticationService::validateSuperUserInitialSignIn()");
		AuthenticationBean authenticationBean = null;
		try{
			RamSystemSettings systemSettings = dbUtilsDAO
					.getSystemSettings(RoosterConstants.SUPER_USER_INITIAL_LOGIN);
			if (systemSettings.getSettingValue().equals(RoosterConstants.TRUE)) {
				throw new RoosterCoreException(
						NErrorCode.INVALID_SUPER_USER_LOGIN,
						dbUtilsDAO
								.getSystemSettings(RoosterConstants.GENERAL_LOGIN_URL).getSettingValue());
			}

			RamLogins ramLogins = authenticationDaoI.login(loginBean);

			if (ramLogins == null) {
				throw new LoginException(NErrorCode.INVALID_SU_LOGIN_AUTHENTICATION);
			}
		
			authenticationBean = mapAuthenticationBean(ramLogins);
			if(!authenticationBean.getRole().contains(RoosterConstants.SUPER_USER)){
				throw new LoginException(NErrorCode.INVALID_SU_LOGIN_AUTHENTICATION);
			};
			
			systemSettings.setSettingValue(RoosterConstants.TRUE);
			dbUtilsDAO.updateSystemSettings(systemSettings);
		}catch (UnknownSystemKeyException unknownSystemKeyException) {
			LOGGER.error(unknownSystemKeyException.getNErrorCode(), unknownSystemKeyException);
			throw new RoosterCoreException(NErrorCode.UNDEFINED_EXCEPTION);
		}
		
		LOGGER.info("Exit::Authentication::AuthenticationService::validateSuperUserInitialSignIn()");
		return authenticationBean;
	}

	private AuthenticationBean mapAuthenticationBean(RamLogins ramLogins) {
		LOGGER.info("Entered::Authentication::AuthenticationService::mapAuthenticationBean()");
		AuthenticationBean authenticationBean = new AuthenticationBean();
		authenticationBean.setAccessToken("I have to generate Access token");
		authenticationBean.setUserID(ramLogins.getRamUsers().getUserId());
		authenticationBean.setFirstName(ramLogins.getRamUsers()
				.getUserFirstName());
		authenticationBean.setLastName(ramLogins.getRamUsers()
				.getUserLastName());
		List<String> list = new ArrayList<String>();
		for (RamRoles ramRoles : ramLogins.getRamUsers().getRamRoles()) {
			list.add(ramRoles.getRoleName());
		}

		authenticationBean.setRole(list);
		LOGGER.info("Exit::Authentication::AuthenticationService::mapAuthenticationBean()");
		return authenticationBean;
	}

	public void updateUserCredentials(LoginBean loginBean) {
		LOGGER.info("Entered::Authentication::AuthenticationService::updateUserCredentials()"+ loginBean.getUserID());
		
		LoginBean bean = new LoginBean();
		bean.setUsername(loginBean.getUsername());
		bean.setPassword(loginBean.getOldPassword());
		
		RamLogins ramLogins = authenticationDaoI.login(loginBean);

		if (ramLogins == null) {
			throw new RoosterCoreException(NErrorCode.INVALID_CREDENTIALS_FOR_UPDATE_OF_LOGIN_CREDENTIALS);
		}
		ramLogins.setPassword(loginBean.getPassword());

		
		
		LOGGER.info("Exit::Authentication::AuthenticationService::updateUserCredentials()::UserID::"+ loginBean.getUserID());
		
	}

}
